<?php

namespace App\Logic;

use App\Model\ActivityApplyModel;
use App\Model\ActivityModel;
use App\Model\ActivityReportDetailModel;
use App\Model\ActivityReportModel;
use App\Model\ConsumeOrderModel;
use App\Model\CouponsUserModel;
use App\Model\RewardOrderModel;
use App\Model\UserModel;
use App\Model\UserMoneyLogModel;
use App\Model\UserMoneyModel;
use App\Model\UserPartakeModel;
use App\Utility\CommonTool;
use EasySwoole\Http\Message\Status;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\Db\ClientInterface;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Pool\Exception\PoolEmpty;
use EasySwoole\Pool\Manager;
use Throwable;

class ActivityLogic
{
    /**
     * 加入赛事
     * @param int $userId 用户ID
     * @param int $activityId 赛事ID
     * @param int $couponsId 优惠券ID
     * @param float $money 金额
     * @param int $journalType 流水账类型
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public static function joinActivity(int $userId, int $activityId, int $couponsId, float $money, int $journalType)
    {
        $res = [];
        DbManager::getInstance()->invoke(function (ClientInterface $client) use ($userId, $activityId, $couponsId, $money, $journalType, &$res) {
            try {
                // 查找用户单张优惠券
                if ($couponsId > 0) {
                    $couponsUserInfo = CouponsUserModel::invoke($client)->findCouponsById($couponsId);
                    if ($couponsUserInfo) {
                        $offerMoney = $couponsUserInfo->offer_money;
                    } else {
                        $res = [
                            "code" => Status::CODE_BAD_REQUEST,
                            "result" => [],
                            "msg" => "该用户没有该优惠券"
                        ];
                        return false;
                    }
                } else {
                    $offerMoney = 0;
                }

                // 查找用户信息
                $user = UserModel::invoke($client)->get($userId);
                if (!$user) {
                    $res = [
                        "code" => Status::CODE_BAD_REQUEST,
                        "result" => [],
                        "msg" => "没有该用户信息"
                    ];
                    return false;
                }

                // 查找用户余额信息
                $userMoney = UserMoneyModel::invoke($client)->findUserMoney($userId);
                if ($userMoney['balance'] < floatval($money - $offerMoney)) {
                    if ($user->is_real == 1) {
                        $res = [
                            "code" => Status::CODE_BAD_REQUEST,
                            "result" => [],
                            "msg" => "用户余额不足"
                        ];
                        return false;
                    } else {
                        // 虚拟用户不够钱,自动充钱
                        $userMoney = PayLogic::rechargeMoney($userId, $userMoney['balance'], 500000.00, 1);
                    }
                }

                // 查找活动信息
                $activity = ActivityModel::invoke($client)->where('id', $activityId)->where('status', 1)->get();
                if (!$activity) {
                    $res = [
                        "code" => Status::CODE_BAD_REQUEST,
                        "result" => [],
                        "msg" => "该活动已下架"
                    ];
                    return false;
                }

                // 查找用户是否追加 注数
                $activityApplyId = ActivityApplyModel::invoke($client)->changeTableName($userId)->where('user_id', $userId)->where('activity_id', $activityId)->val('id');
                if (!$activityApplyId) {
                    $message = '支付契约金：';
                } else {
                    $message = '追加投注：';
                }
                $message .= CommonTool::getTypeName($activity->btype_id, 1) . '(' . CommonTool::getTypeName($activity->stype_id, 2) . ')-' . date('md', strtotime($activity->name)) . '期';

                // 开启事务
                DbManager::getInstance()->startTransaction($client);

                // 余额扣费
                UserMoneyModel::invoke($client)->updateUserMoney($userId, [
                    'balance' => ['dec', floatval($money - $offerMoney)],
                ]);

                // 添加添加消费记录
                $consumeOrderInsertId = ConsumeOrderModel::invoke($client)->add($userId, $money, $offerMoney, $message);

                // 添加用户流水账记录
                UserMoneyLogModel::invoke($client)->add($userId, $userMoney['balance'], (floatval($money - $offerMoney) * -1), $journalType, $consumeOrderInsertId, $message);

                if (!$activityApplyId) {
                    // 插入申请记录
                    ActivityApplyModel::invoke($client)->changeTableName($userId)->data([
                        'user_id' => $userId,
                        'activity_id' => $activity->id,
                        'reward' => $money,
                        'time' => 1,
                        'multiple' => intval($money / $activity->bet_amount),
                        'create_time' => time(),
                        'update_time' => time(),
                        'sign_time' => 0,
                        'target_time' => $activity->days_held,
                        'status' => 0,
                    ], false)->save();

                    if ($user->is_real == 1) {
                        // 更新赛事信息
                        ActivityModel::invoke($client)->updateActivity($activityId, [
                            'real_reward' => ['inc', floatval($money)],
                            'all_reward' => ['inc', floatval($money)],
                            'real_enrollment' => ['inc', 1],
                            'all_enrollment' => ['inc', 1],
                            'coupons_real_money' => ['inc', floatval($offerMoney)],
                            'coupons_money' => ['inc', floatval($offerMoney)],
                        ]);

                        go(function () use ($userId, $money, $activity) {
                            // 插入真实的有序集合中
                            $redis = Manager::getInstance()->get('redis')->getObj();
                            $redis->zAdd('set_join_real_' . $activity->id, intval($money / $activity->bet_amount), $userId);
                            Manager::getInstance()->get('redis')->recycleObj($redis);
                        });
                    } else {
                        // 更新赛事信息
                        ActivityModel::invoke($client)->updateActivity($activityId, [
                            'virtual_reward' => ['inc', floatval($money)],
                            'all_reward' => ['inc', floatval($money)],
                            'virtual_enrollment' => ['inc', 1],
                            'all_enrollment' => ['inc', 1],
                            'coupons_real_money' => ['inc', floatval($offerMoney)],
                            'coupons_money' => ['inc', floatval($offerMoney)],
                        ]);

                        go(function () use ($userId, $money, $activity) {
                            // 插入虚拟的有序集合中
                            $redis = Manager::getInstance()->get('redis')->getObj();
                            $redis->zAdd('set_join_fictitious_' . $activity->id, intval($money / $activity->bet_amount), $userId);
                            Manager::getInstance()->get('redis')->recycleObj($redis);
                        });
                    }

                    // 插入或更新排行榜
                    $userPartakeId = UserPartakeModel::invoke($client)->where('user_id', $userId)->val('id');
                    if (!$userPartakeId) {
                        UserPartakeModel::invoke($client)->data([
                            'user_id' => $userId,
                            'partake_num' => 1,
                            'ongoing_num' => 1,
                            'finish_num' => 0,
                            'finish_percent' => 0,
                            'prize' => 0,
                            'create_time' => time(),
                            'update_time' => time(),
                        ], false)->save();
                    } else {
                        UserPartakeModel::invoke($client)->update([
                            'partake_num' => QueryBuilder::inc(1),
                            'ongoing_num' => QueryBuilder::inc(1),
                            'update_time' => time(),
                        ], ['id' => $userPartakeId]);
                    }
                } else {
                    // 更新申请记录
                    ActivityApplyModel::invoke($client)->update([
                        'time' => QueryBuilder::inc(1),
                        'reward' => QueryBuilder::inc($money),
                        'multiple' => QueryBuilder::inc(intval($money / $activity->bet_amount)),
                    ], ['id' => $activityApplyId]);

                    if ($user->is_real == 1) {
                        // 更新赛事信息
                        ActivityModel::invoke($client)->updateActivity($activityId, [
                            'real_reward' => ['inc', floatval($money)],
                            'all_reward' => ['inc', floatval($money)],
                            'coupons_real_money' => ['inc', floatval($offerMoney)],
                            'coupons_money' => ['inc', floatval($offerMoney)],
                        ]);

                        go(function () use ($userId, $money, $activity) {
                            // 插入真实的有序集合中
                            $redis = Manager::getInstance()->get('redis')->getObj();
                            $redis->zInCrBy('set_join_real_' . $activity->id, intval($money / $activity->bet_amount), $userId);
                            Manager::getInstance()->get('redis')->recycleObj($redis);
                        });
                    } else {
                        // 更新赛事信息
                        ActivityModel::invoke($client)->updateActivity($activityId, [
                            'virtual_reward' => ['inc', floatval($money)],
                            'all_reward' => ['inc', floatval($money)],
                            'coupons_real_money' => ['inc', floatval($offerMoney)],
                            'coupons_money' => ['inc', floatval($offerMoney)],
                        ]);

                        go(function () use ($userId, $money, $activity) {
                            // 插入虚拟的有序集合中
                            $redis = Manager::getInstance()->get('redis')->getObj();
                            $redis->zInCrBy('set_join_fictitious_' . $activity->id, intval($money / $activity->bet_amount), $userId);
                            Manager::getInstance()->get('redis')->recycleObj($redis);
                        });
                    }
                }

                if ($couponsId > 0) {
                    // 更新用户优惠券,已使用
                    CouponsUserModel::invoke($client)->update([
                        'status' => 2,
                        'used_time' => time(),
                        'consume_id' => $consumeOrderInsertId,
                    ], ['id' => $couponsId]);
                }

                go(function () use ($userId, $activity) {
                    $redis = Manager::getInstance()->get('redis')->getObj();
                    $redis->sAdd('set_join_' . $activity->id, $userId);
                    Manager::getInstance()->get('redis')->recycleObj($redis);
                });

                return true;
            } catch (Throwable  $e) {
                // 回滚事务
                DbManager::getInstance()->rollback($client);
                $res = [
                    "code" => Status::CODE_BAD_REQUEST,
                    "result" => [],
                    "msg" => $e->getMessage()
                ];
                return false;
            } finally {
                // 提交事务
                DbManager::getInstance()->commit($client);
                if (count($res) <= 0) {
                    $res = [
                        "code" => Status::CODE_OK,
                        "result" => [],
                        "msg" => "success"
                    ];
                    return true;
                } else {
                    return false;
                }
            }
        });

        return $res;
    }

    /**
     * 瓜分奖金逻辑
     * @return bool
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public static function splitMoney()
    {
        $activityArray = DbManager::getInstance()->invoke(function ($client) {
            return ActivityModel::invoke($client)
                ->where('status', 1)
                ->where('end_date', date('Y-m-d'), '<=')
                ->where('end_time', date('H:i:s'), '<=')
                ->order('id', 'asc')
                ->all();
        });

        if (count($activityArray) <= 0) {
            return false;
        }

        foreach ($activityArray as $k => $v) {
            $endDateTime = strtotime($v->end_date . ' ' . $v->end_time);
            if ($endDateTime > time()) {
                continue;
            }

            // 更新真实用户申请表签到失败
            $failRealUsers = self::updateRealUserToFail($v);

            if ($v->game_type == 1) {
                if (count($failRealUsers) <= 0) {
                    // 正常签到
                    self::normalActivity($v);
                }
            } elseif ($v->game_type == 2) {
                // 排位签到
                self::rankActivity($v);
            }

            // 返回统计数据,测试用户,失败用户
            $temp = self::returnData($v);

            $successRealEnrollment = 0; // 成功完成任务人数(真实)
            $successVirtualEnrollment = 0; // 成功完成任务人数(虚拟)
            $successRealMoney = 0.00; // 成功完成任务金额(真实)
            $successVirtualMoney = 0.00; // 成功完成任务金额(虚拟)
            $failRealEnrollment = 0; // 失败结束任务人数(真实)
            $failVirtualEnrollment = 0; // 失败结束任务人数(虚拟)
            $failRealMoney = 0.00; // 失败结束任务金额(真实)
            $failVirtualMoney = 0.00; // 失败结束任务金额(虚拟)
            $successRealReward = 0.00; // 成功完成任务瓜分金额(真实)
            $successRealMultiple = 0; // 成功完成任务注数(真实)
            $list = [];
            $halveMoney = 0; // 查询等待瓜分的金额（真实+虚拟）
            $allMultiple = 0; // 查询等待瓜分的倍数（真实+虚拟）
            foreach ($temp['count'] as $count) {
                foreach ($count as $one) {
                    if ($one->status == 1 && $one->is_real == 1) {
                        $successRealEnrollment += $one->enrollment;  // 成功完成任务人数(真实)
                        $successRealMoney += $one->amount; // 成功完成任务金额(真实)
                    } elseif ($one->status == 2 && $one->is_real == 1) {
                        $failRealEnrollment += $one->enrollment; // 失败结束任务人数(真实)
                        $failRealMoney += $one->amount; // 失败结束任务金额(真实)
                    } elseif ($one->status == 1 && $one->is_real == 2) {
                        $successVirtualEnrollment += $one->enrollment; // 成功完成任务人数(虚拟)
                        $successVirtualMoney += $one->amount; // 成功完成任务金额(虚拟)
                    } elseif ($one->status == 2 && $one->is_real == 2) {
                        $failVirtualEnrollment += $one->enrollment; // 失败结束任务人数(虚拟)
                        $failVirtualMoney += $one->amount; // 失败结束任务金额(虚拟)
                    }

                    if ($one->status == 2) {
                        $halveMoney += $one->amount;
                    } else {
                        $allMultiple += ($one->multiple * $one->enrollment);
                    }

                    $tmpName = md5($one->activity_id . $one->status . $one->multiple . $one->is_real);
                    if (isset($list[$tmpName])) {
                        $list[$tmpName] = [
                            'activity_id' => $one->activity_id,
                            'multiple' => $list[$tmpName]['multiple'] + $one->multiple, // 报名注数
                            'enrollment' => $list[$tmpName]['enrollment'] + $one->enrollment, // 报名人数
                            'amount' => $list[$tmpName]['amount'] + $one->amount, // 报名金额
                            'type' => $one->status, // 类型1:成功，2:失败
                            'is_real' => $one->is_real, // 是否虚拟用户，1为真实，2为虚拟
                        ];
                    } else {
                        $list[$tmpName] = [
                            'activity_id' => $one->activity_id,
                            'multiple' => $one->multiple, // 报名注数
                            'enrollment' => $one->enrollment, // 报名人数
                            'amount' => $one->amount, // 报名金额
                            'type' => $one->status, // 类型1:成功，2:失败
                            'is_real' => $one->is_real, // 是否虚拟用户，1为真实，2为虚拟
                        ];
                    }
                }
            }
            DbManager::getInstance()->invoke(function ($client) use ($list) {
                ActivityReportDetailModel::invoke($client)->saveAll($list);
            });

            // 平均每注等奖数
            if ($allMultiple > 0) {
                $avgAmount = floatval(floatval($halveMoney) / floatval($allMultiple));
            } else {
                $avgAmount = 0;
            }

            // 插入活动赛事报告表
            $reportData = [
                'activity_id' => $v->id,
                'success_enrollment' => $successRealEnrollment + $successVirtualEnrollment, // 成功完成任务人数
                'success_real_enrollment' => $successRealEnrollment, // 成功完成任务人数(真实)
                'success_virtual_enrollment' => $successVirtualEnrollment, // 成功完成任务人数(虚拟)
                'success_money' => $successRealMoney + $successVirtualMoney, // 成功完成任务金额
                'success_real_money' => $successRealMoney, // 成功完成任务金额(真实) (待退回本金)
                'success_virtual_money' => $successVirtualMoney, // 成功完成任务金额(虚拟)
                'fail_enrollment' => $failRealEnrollment + $failVirtualEnrollment, // 失败结束任务人数
                'fail_real_enrollment' => $failRealEnrollment, // 失败结束任务人数(真实)
                'fail_virtual_enrollment' => $failVirtualEnrollment, // 失败结束任务人数(虚拟)
                'fail_money' => $failRealMoney + $failVirtualMoney, // 失败结束任务金额(待瓜分金额)
                'fail_real_money' => $failRealMoney, // 失败结束任务金额(真实)
                'fail_virtual_money' => $failVirtualMoney, // 失败结束任务金额(虚拟)
                'avg_reward' => $avgAmount, // 平均成功完成任务每一注奖金
            ];
            $reportInsertId = DbManager::getInstance()->invoke(function ($client) use ($reportData) {
                return ActivityReportModel::invoke($client)->data($reportData, false)->save();
            });

            foreach ($temp['success'] as $one) {
                // 得到用户瓜分的金额
                $reward = round(floatval($avgAmount * $one->multiple), 2);

                if ($one->is_real == 1) {
                    $successRealReward += $reward;
                    $successRealMultiple += $one->multiple;
                }

                DbManager::getInstance()->invoke(function ($client) use ($one, $reward, $v) {
                    $userMoney = UserMoneyModel::invoke($client)->where('user_id', $one->user_id)->get();

                    // 插入用户奖励金额表
                    $rewardOrderIds = RewardOrderModel::invoke($client)->saveAll([
                        [
                            'user_id' => $one->user_id,
                            'activity_id' => $one->activity_id,
                            'type' => 1,
                            'reward' => $reward,
                            'create_time' => time(),
                        ],
                        [
                            'user_id' => $one->user_id,
                            'activity_id' => $one->activity_id,
                            'type' => 2,
                            'reward' => $one->reward,
                            'create_time' => time(),
                        ],
                    ]);

                    // 添加用户流水账记录
                    UserMoneyLogModel::invoke($client)->add($one->user_id, $userMoney->balance, (round(floatval($reward), 2)), 1, $rewardOrderIds[0], '奖金:' . CommonTool::getTypeName($v->btype_id, 1) . '(' . CommonTool::getTypeName($v->stype_id, 2) . ')-' . date('md', strtotime($v->name)) . '期');
                    UserMoneyLogModel::invoke($client)->add($one->user_id, $userMoney->balance, (round(floatval($one->reward), 2)), 1, $rewardOrderIds[1], '本金:' . CommonTool::getTypeName($v->btype_id, 1) . '(' . CommonTool::getTypeName($v->stype_id, 2) . ')-' . date('md', strtotime($v->name)) . '期');

                    // 更新到用户的余额表
                    UserMoneyModel::invoke($client)->updateUserMoney($one->user_id, [
                        'amount' => ['inc', round(floatval($reward), 2)],
                        'balance' => ['inc', round(floatval($reward + $one->reward), 2)]
                    ]);

                    // 插入用户进入排行
                    self::updateUserPartake($one->user_id, 1, $reward);
                });
            }

            foreach ($temp['fail'] as $one) {
                // 插入用户进入排行
                self::updateUserPartake($one->user_id, 0, 0);
            }

            DbManager::getInstance()->invoke(function ($client) use ($successRealReward, $successRealMultiple, $reportInsertId) {
                // 更新活动赛事报告表
                $report = ActivityReportModel::invoke($client)->get($reportInsertId);
                $report->success_real_reward = $successRealReward;
                $report->success_virtual_reward = $report->fail_money - $successRealReward;
                $report->success_real_multiple = $successRealMultiple;
                $report->update();

                // 活动赛事下架
                ActivityModel::invoke($client)->update(['update_time' => time(), 'status' => '2',], ['id' => $report->activity_id,]);
            });
        }

        return true;
    }

    /**
     * 正常签到
     * @param ActivityModel $activityObj
     * @throws Throwable
     */
    private static function normalActivity(ActivityModel $activityObj): void
    {
        $listCount = 0;
        $setCount = 0;
        $redis = Manager::getInstance()->get('redis')->getObj();
        if ($redis->exists('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)))) {
            $listCount = $redis->lLen('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)));
        }
        if ($redis->exists('set_join_' . $activityObj->id)) {
            $setCount = intval($redis->sCard('set_join_' . $activityObj->id));
        }
        Manager::getInstance()->get('redis')->recycleObj($redis);

        // 当申请人数 等于 签到人数
        // 且
        // (赛事可以 追加 且 举行一天
        // 或
        // 赛事可以 追加 且 举行七天)
        if (($setCount == $listCount) && (($activityObj->is_add == 1 && $activityObj->days_held == 1) || ($activityObj->is_add == 1 && $activityObj->days_held == 7))) {
            $tempBoolean = false;
            $virtualUsers = [];
            $redis = Manager::getInstance()->get('redis')->getObj();
            if ($redis->exists('set_join_fictitious_' . $activityObj->id)) {
                $virtualUsers = $redis->zRangeByScore('set_join_fictitious_' . $activityObj->id, '-inf', '+inf', ['limit' => array(0, 1)]);
                $tempBoolean = true;
            }
            Manager::getInstance()->get('redis')->recycleObj($redis);

            if ($tempBoolean) {
                DbManager::getInstance()->invoke(function ($client) use ($activityObj, $virtualUsers) {
                    foreach ($virtualUsers as $k => $v) {
                        ActivityApplyModel::invoke($client)->changeTableName($v)->update(['status' => '2', 'update_time' => time(), 'sign_time' => '0',], ['user_id' => $v, 'activity_id' => $activityObj->id,]);
                    }
                });
            }
        }
    }

    /**
     * 排位签到
     * @param ActivityModel $activityObj
     * @throws Throwable
     */
    private static function rankActivity(ActivityModel $activityObj): void
    {
        $setCount = 0;
        $listCount = 0;
        $listData = [];
        $redis = Manager::getInstance()->get('redis')->getObj();
        if ($redis->exists('set_join_' . $activityObj->id)) {
            $setCount = intval($redis->sCard('set_join_' . $activityObj->id));
        }
        if ($redis->exists('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)))) {
            $listCount = $redis->lLen('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)));
            $listData = $redis->lRange('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)), 0, -1);
        }
        Manager::getInstance()->get('redis')->recycleObj($redis);

        $outRate = 5;
        $outRateRule = [
            '27' => 3,
            '28' => 4,
            '29' => 5,
        ];
        foreach ($outRateRule as $k => $v) {
            if ($k == $activityObj->stype_id) {
                $outRate = $v;
                break;
            }
        }

        // 得到排位竞赛,要筛选出多小个出来
        $outNum = floor($setCount * $outRate / 100);
        if ($outNum == 0) {
            $outNum = 1;
        }

        if (($setCount - $listCount) < $outNum) {
            if (($setCount - $listCount) == 0) {
                $tmp = $outNum;
            } else {
                $tmp = $outNum - ($setCount - $listCount);
            }

            if ($listCount > 0) {
                foreach ($listData as $k => $v) {
                    if (($k + 1) == $tmp) {
                        break;
                    }
                    DbManager::getInstance()->invoke(function ($client) use ($activityObj, $k, $v) {
                        ActivityApplyModel::invoke($client)->changeTableName($k)->update([
                            'status' => '2', 'update_time' => time(),
                        ], ['user_id' => $v, 'activity_id' => $activityObj->id,]);
                    });
                }
            }
        }
    }

    /**
     * 更新用户进入排行
     * @param int $userId
     * @param int $status
     * @param int $prize
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    private static function updateUserPartake(int $userId, int $status, int $prize)
    {
        $partake = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return UserPartakeModel::invoke($client)->where('user_id', $userId)->get();
        });

        if (!$partake) {
            // 新增
            if ($status) {
                $finishPercent = 100.00;
                $tmpPrize = $prize;
            } else {
                $finishPercent = 0.00;
                $tmpPrize = 0.00;
            }

            DbManager::getInstance()->invoke(function ($client) use ($partake, $status, $finishPercent, $tmpPrize, $userId) {
                return UserPartakeModel::invoke($client)->addUserPartake($userId, $status, $finishPercent, $tmpPrize);
            });
        } else {
            // 修改
            if ($partake->ongoing_num >= 1) {
                if ($status) {
                    $finishNum = $partake->finish_num + 1;
                    $prize = $partake->prize + $prize;
                } else {
                    $finishNum = $partake->finish_num;
                    $prize = $partake->prize;
                }

                if ($finishNum > 0) {
                    $finishPercent = round(($finishNum / ($partake->partake_num + 1)) * 100, 2);
                } else {
                    $finishPercent = 0.00;
                }

                DbManager::getInstance()->invoke(function ($client) use ($partake, $finishNum, $finishPercent, $prize) {
                    return UserPartakeModel::invoke($client)->updateUserPartake($partake->id, [
                        'partake_num' => ['inc', 1],
                        'ongoing_num' => ['dec', 1],
                        'finish_num' => $finishNum,
                        'finish_percent' => $finishPercent,
                        'prize' => $prize,
                        'update_time' => time(),
                    ]);
                });
            }
        }
    }

    /**
     * 返回统计数据,测试用户,失败用户
     * @param ActivityModel $activityObj
     * @return mixed|void
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    private static function returnData(ActivityModel $activityObj)
    {
        return DbManager::getInstance()->invoke(function ($client) use ($activityObj) {
            $res = [];
            $successTmp = [];
            $failTmp = [];

            for ($i = 1; $i <= 100; $i++) {
                // 查询100个表的
                $res['count'][$i] = ActivityApplyModel::invoke($client)
                    ->changeTableName($i)
                    ->field(['aa.activity_id', 'aa.multiple', 'COUNT(aa.user_id) as enrollment', 'SUM(aa.reward) as amount', 'aa.status', 'u.is_real'])
                    ->alias('aa')
                    ->join('bee_user u', 'aa.user_id = u.id')
                    ->where('aa.activity_id', $activityObj->id)
                    ->group('aa.activity_id, aa.status, aa.multiple, u.is_real')
                    ->all();

                $successTmp[$i] = ActivityApplyModel::invoke($client)
                    ->changeTableName($i)
                    ->field(['aa.id', 'aa.user_id', 'aa.multiple', 'aa.reward', 'u.is_real'])
                    ->alias('aa')
                    ->join('bee_user u', 'aa.user_id = u.id')
                    ->where('aa.activity_id', $activityObj->id)
                    ->where('aa.status', 1)
                    ->all();

                $failTmp[$i] = ActivityApplyModel::invoke($client)
                    ->changeTableName($i)
                    ->field(['aa.id', 'aa.user_id', 'aa.multiple', 'aa.reward', 'u.is_real'])
                    ->alias('aa')
                    ->join('bee_user u', 'aa.user_id = u.id')
                    ->where('aa.activity_id', $activityObj->id)
                    ->where('aa.status', 2)
                    ->all();
            }

            $res['success'] = array_reduce(array_filter($successTmp), 'array_merge', array());
            $res['fail'] = array_reduce(array_filter($failTmp), 'array_merge', array());

            return $res;
        });
    }

    /**
     * 更新真实用户申请表签到失败
     * @param ActivityModel $activityObj
     * @return array
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    private static function updateRealUserToFail(ActivityModel $activityObj)
    {
        $setCount = 0;
        $listCount = 0;
        $listData = [];
        $realUsers = [];
        $redis = Manager::getInstance()->get('redis')->getObj();
        if ($redis->exists('set_join_' . $activityObj->id)) {
            $setCount = intval($redis->sCard('set_join_' . $activityObj->id));
        }
        if ($redis->exists('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)))) {
            $listCount = $redis->lLen('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)));
            $listData = $redis->lRange('list_' . $activityObj->id . '_' . date('Ymd', strtotime($activityObj->end_date)), 0, -1);
        }
        if ($redis->exists('set_join_real_' . $activityObj->id)) {
            $realUsers = $redis->zRange('set_join_real_' . $activityObj->id, '-inf', '+inf');
        }
        Manager::getInstance()->get('redis')->recycleObj($redis);

        // 申请的用户 > 签到的用户
        // 说明有用户打卡失败
        if ($setCount > $listCount) {
            $failRealUsers = [];
            foreach ($realUsers as $realUser) {
                if (!in_array($realUser, $listData)) {
                    $failRealUsers[] = $realUser;
                }
            }

            $res = DbManager::getInstance()->invoke(function ($client) use ($activityObj, $failRealUsers) {
                try {
                    //开启事务
                    DbManager::getInstance()->startTransaction($client);
                    foreach ($failRealUsers as $failRealUser) {
                        // 更新挑战失败签到赛事的用户状态
                        ActivityApplyModel::invoke($client)
                            ->changeTableName($failRealUser)
                            ->update(['status' => '2', 'update_time' => time()], ['activity_id' => $activityObj->id, 'status' => 0, 'sign_time' => [$activityObj->days_held, '<']]);
                    }
                    return true;
                } catch (Throwable  $e) {
                    // 回滚事务
                    DbManager::getInstance()->rollback($client);
                    return false;
                } finally {
                    // 提交事务
                    DbManager::getInstance()->commit($client);
                }
            });

            if ($res) {
                return $failRealUsers;
            } else {
                return [];
            }
        } else {
            return [];
        }
    }
}
